From 54e8bd898a55eec8b3ff966482400b9ec47f7a9e Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 1 Apr 2023 12:48:26 +0200 Subject: [PATCH] wayland: Add support for the fractional scale protocol April fools! No, really. The fractional scale protocol is just a way to track the surface scale, but not a way to draw fractional content. This commit uses it for that, so tht we don't rely on tracking outputs. This also allows magnifiers etc to send us a larger (integer) scale if they would like that, that is not represented by the outputs. --- gdk/wayland/gdkdisplay-wayland.c | 8 ++++ gdk/wayland/gdkdisplay-wayland.h | 2 + gdk/wayland/gdksurface-wayland-private.h | 1 + gdk/wayland/gdksurface-wayland.c | 47 +++++++++++++++++++----- gdk/wayland/meson.build | 1 + 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 5a5533badb..541f34789c 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -509,6 +509,14 @@ gdk_registry_handle_global (void *data, &xdg_activation_v1_interface, MIN (version, XDG_ACTIVATION_VERSION)); } + else if (strcmp (interface, "wp_fractional_scale_manager_v1") == 0) + { + display_wayland->fractional_scale = + wl_registry_bind (display_wayland->wl_registry, id, + &wp_fractional_scale_manager_v1_interface, + MIN (version, 1)); + } + g_hash_table_insert (display_wayland->known_globals, GUINT_TO_POINTER (id), g_strdup (interface)); diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index 332e30259d..6dbe793157 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -111,6 +112,7 @@ struct _GdkWaylandDisplay struct zxdg_output_manager_v1 *xdg_output_manager; struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; struct xdg_activation_v1 *xdg_activation; + struct wp_fractional_scale_manager_v1 *fractional_scale; GList *async_roundtrips; diff --git a/gdk/wayland/gdksurface-wayland-private.h b/gdk/wayland/gdksurface-wayland-private.h index 0ecd0763f3..4689945cc7 100644 --- a/gdk/wayland/gdksurface-wayland-private.h +++ b/gdk/wayland/gdksurface-wayland-private.h @@ -35,6 +35,7 @@ struct _GdkWaylandSurface struct xdg_surface *xdg_surface; struct zxdg_surface_v6 *zxdg_surface_v6; struct wl_egl_window *egl_window; + struct wp_fractional_scale_v1 *fractional_scale; } display_server; struct wl_event_queue *event_queue; diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c index 38d3cb54e0..7c952af083 100644 --- a/gdk/wayland/gdksurface-wayland.c +++ b/gdk/wayland/gdksurface-wayland.c @@ -28,7 +28,6 @@ #include "gdkmonitor-wayland.h" #include "gdkpopupprivate.h" #include "gdkprivate-wayland.h" -#include "gdkprivate-wayland.h" #include "gdkseat-wayland.h" #include "gdksurfaceprivate.h" #include "gdktoplevelprivate.h" @@ -426,12 +425,14 @@ gdk_wayland_surface_update_scale (GdkSurface *surface) guint32 scale; GSList *l; + /* We can't set the scale on this surface */ if (!impl->display_server.wl_surface || wl_surface_get_version (impl->display_server.wl_surface) < WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION) - { - /* We can't set the scale on this surface */ - return; - } + return; + + /* scale is tracked by the fractional scale extension */ + if (impl->display_server.fractional_scale) + return; if (!impl->display_server.outputs) { @@ -797,6 +798,24 @@ gdk_wayland_surface_sync_buffer_scale (GdkSurface *surface) impl->buffer_scale_dirty = FALSE; } +static void +gdk_wayland_surface_fractional_scale_preferred_scale_cb (void *data, + struct wp_fractional_scale_v1 *fractional_scale, + uint32_t scale) +{ + GdkWaylandSurface *self = GDK_WAYLAND_SURFACE (data); + GdkSurface *surface = GDK_SURFACE (self); + + /* Notify app that scale changed */ + gdk_wayland_surface_maybe_resize (surface, + surface->width, surface->height, + ceil (scale / 120.0)); +} + +static const struct wp_fractional_scale_v1_listener fractional_scale_listener = { + gdk_wayland_surface_fractional_scale_preferred_scale_cb, +}; + static void surface_enter (void *data, struct wl_surface *wl_surface, @@ -848,15 +867,23 @@ static const struct wl_surface_listener surface_listener = { void gdk_wayland_surface_create_wl_surface (GdkSurface *surface) { - GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + GdkWaylandSurface *self = GDK_WAYLAND_SURFACE (surface); GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface)); struct wl_surface *wl_surface; wl_surface = wl_compositor_create_surface (display_wayland->compositor); - wl_proxy_set_queue ((struct wl_proxy *) wl_surface, impl->event_queue); - wl_surface_add_listener (wl_surface, &surface_listener, surface); + wl_proxy_set_queue ((struct wl_proxy *) wl_surface, self->event_queue); + wl_surface_add_listener (wl_surface, &surface_listener, self); + if (display_wayland->fractional_scale) + { + self->display_server.fractional_scale = + wp_fractional_scale_manager_v1_get_fractional_scale (display_wayland->fractional_scale, + wl_surface); + wp_fractional_scale_v1_add_listener (self->display_server.fractional_scale, + &fractional_scale_listener, self); + } - impl->display_server.wl_surface = wl_surface; + self->display_server.wl_surface = wl_surface; } static void @@ -1024,6 +1051,8 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface) impl->initial_configure_received = FALSE; } + g_clear_pointer (&impl->display_server.fractional_scale, wp_fractional_scale_v1_destroy); + g_clear_pointer (&impl->display_server.wl_surface, wl_surface_destroy); g_slist_free (impl->display_server.outputs); diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build index e5ca9ae02f..67d16e01f5 100644 --- a/gdk/wayland/meson.build +++ b/gdk/wayland/meson.build @@ -65,6 +65,7 @@ proto_sources = [ ['xdg-output', 'unstable', 'v1', ], ['idle-inhibit', 'unstable', 'v1', ], ['xdg-activation', 'staging', 'v1', ], + ['fractional-scale', 'staging', 'v1', ], ] gdk_wayland_gen_headers = [] -- 2.30.2